<?php
/**
 * Created by PhpStorm.
 * User: Zhoujinda
 * Date: 2016/3/15
 * Time: 19:38
 */

namespace app\index\domain;

use app\shop\api\AddressApi;
use app\shop\api\OrdersApi;
use app\shop\api\ShoppingCartApi;
use app\shop\api\StorePromotionApi;
use app\admin\api\OrdersPaycodeApi;
use app\shop\model\Orders;
use app\shop\api\ProductSkuApi;
use app\shop\api\ProductApi;
use app\shop\api\WalletApi;
use app\shop\api\ProductAttrApi;
use app\shop\api\OrdersItemApi;
use app\shop\api\OrdersInfoViewApi;
use app\shop\api\OrderStatusApi;
use app\shop\api\OrderRefundApi;
use app\shop\api\OrdersExpressApi;
use app\shop\api\OrderCommentAttachsApi;
use app\shop\api\OrderCommentApi;
use app\bbs\api\FilterKeyWordsApi;
use app\admin\api\MessageApi;
use app\admin\model\Message;
use app\shop\api\AlipayNotifyApi;
use app\shop\api\ProductPackageApi;
use app\shop\api\ProductPackageItemApi;
use app\shop\api\ProductImageApi;
// use Shop\Api\MemberConfigApi;
use app\shop\api\RedEnvelopeApi;
use app\shop\api\RedEnvelopeTplApi;
use app\shop\api\CouponApi;
use app\shop\api\CouponTplApi;

class OrdersDomain extends BaseDomain{

    protected $business_code = "orders";

    //使订单(仅商城订单) 变为 支付完成状态(支付宝)
    public function testPaySuc(){
        $this->apiReturnErr('接口已关闭');
        // if(IS_POST){
        //     //orders_paycode
        //     //order_status_history+orders
        //     $this->checkVersion($this->api_ver);
        //     addLog("Orders/testPay",$_GET,$_POST,"应用" . $this->client_id . "调用订单强制支付接口");
        //     $uid    = $this->_post("uid",0,"缺少用户ID");
        //     $code   = $this->_post("code",'',"缺少订单编号");
        //     $pay_type = 1;
        //     $p_pos  = strpos($code,"P");
        //     $pay_id = substr($code,$p_pos+1,strlen($code)-$p_pos);
        //     //查询订单信息
        //     $r = apiCall(OrdersPaycodeApi::GET_INFO,[['id'=>$pay_id]]);
        //     if(!$r['status']) $this->apiReturnErr($r['info']);
        //     if(empty($r['info'])) $this->apiReturnErr('id错误');
        //     $order_codes_str = $r['info']['order_content'];
        //     $total_fee = $r['info']['pay_money'];
        //     //支付 状态
        //     $model = new \think\model\Adv();
        //     $model ->startTrans();
        //     $r = apiCall(OrdersPaycodeApi::SAVE,[['id'=>$pay_id],['pay_type'=>$pay_type,'pay_status'=>1,'order_status'=>3]]);
        //     $this->checkApiReturn($r,false,false,$model);
        //     $order_codes = explode(';', $order_codes_str);
        //     array_pop($order_codes);
        //     foreach ($order_codes as $v) {
        //         //支付 状态
        //         $r = apiCall(OrderStatusApi::PAY_ORDER,[$code,$v,$uid,$pay_type]);
        //         $this->checkApiReturn($r,false,false,$model);
        //     }
        //     //             INSERT INTO `itboye_mengwu`.`itboye_alipay_notify` 
        //     // (`id`, `discount`, `payment_type`, `subject`, `trade_no`, `buyer_email`, `gmt_create`, `notify_type`, `quantity`, `out_trade_no`, `seller_id`, `notify_time`, `body`, `trade_status`, `is_total_fee_adjust`, `total_fee`, `gmt_payment`, `seller_email`, `price`, `buyer_id`, `notify_id`, `use_coupon`, `sign_type`, `sign`) VALUES 
        //     // ('8', '0.00', '1', '订单T1459414696U18P149', '2016033121001004920247617255', 'bierqi@163.com', '2016', 'trade_status_sync', '1', 'T1459414696U18P149', '2088122913686583', '2016', '订单T1459414696U18P149', 'TRADE_SUCCESS', 'N', '0.01', '2016', '1580468651@qq.com', '0.01', '2088202272162921', '4712a6d202e08ff2105f1d710978e39n3m', 'N', 'RSA', 'dV9G6bfXTgcH5WVPdFgFKPyVVmrjG6jeOcb0rrIml9teYd/06Ef2F44Tk5E+BquguFM+KXOXGc4d5RScfAkgrJxbHsQVJMfxxWc18v67Y2+OP99IIpvHalWzKkJZ4EqyZfxwVSgqkWoFpn+qh/icrPeMsmcmaVDep49C+gEhaeI=');
        //     $entity = [
        //         'payment_type'        => 1,//$_POST['payment_type'],
        //         'subject'             => 'TEST订单'.$code,//$_POST['subject'],
        //         'trade_no'            => '2016033121001004920247617255',//$_POST['trade_no'],
        //         'buyer_email'         => 'bierqi@163.com',//$_POST['buyer_email'],
        //         'gmt_create'          => '2016',//$_POST['gmt_create'],
        //         'notify_type'         => 'trade_status_sync',//$_POST['notify_type'],
        //         'quantity'            => '1',//$_POST['quantity'],
        //         'out_trade_no'        => $code,//$_POST['out_trade_no'],
        //         'seller_id'           => '2088122913686583',//$_POST['seller_id'],
        //         'notify_time'         => time(),//$_POST['notify_time'],
        //         'body'                => 'TEST订单'.$code,//$_POST['body'],
        //         'trade_status'        => 'TRADE_SUCCESS',//$_POST['trade_status'],
        //         'is_total_fee_adjust' => 'N',//$_POST['is_total_fee_adjust'],
        //         'total_fee'           => $total_fee,//$_POST['total_fee'],
        //         'seller_email'        => '1580468651@test.com',//$_POST['seller_email'],
        //         'price'               => $total_fee,//$_POST['price'],
        //         'buyer_id'            => '2088202272162921',//$_POST['buyer_id'],
        //         'notify_id'           => '4712a6d202e08ff2105f1d710978e39n3m',//$_POST['notify_id'],
        //         'use_coupon'          => 'N',//$_POST['use_coupon'],
        //         'sign_type'           => 'RSA',//$_POST['sign_type'],
        //         'sign'                => 'dV9G6bfXTgcH5WVPdFgFKPyVVmrjG6jeOcb0rrIml9teYd/06Ef2F44Tk5E+BquguFM+KXOXGc4d5RScfAkgrJxbHsQVJMfxxWc18v67Y2+OP99IIpvHalWzKkJZ4EqyZfxwVSgqkWoFpn+qh/icrPeMsmcmaVDep49C+gEhaeI=',//$_POST['sign'],
        //         'gmt_payment'         => '2016',//$_POST['gmt_payment']
        //     ];

        //     $r = apiCall(AlipayNotifyApi::ADD,[$entity]);
        //     $this->checkApiReturn($r,false,false,$model);
        //     $model ->commit();
        //     $this->apiReturnSuc('支付完成');
        // }
    }
    /**
     * 订单评价 - 按商品ID规格ID套餐ID分组ID
     * @return [type] [description]
     */
    public function comment(){
        if(IS_POST){
            $this->checkVersion(101);
            addLog("Orders/comment",$_GET,$_POST,"应用" . $this->client_id . "调用订单评价接口");
            //购买人的用户ID
            $uid = $this->_post("uid",0,"缺少用户ID");
            $pid = $this->_post("pid",0,"缺少商品ID");
            $psku_id    = $this->_post("psku_id",0);
            $group_id   = $this->_post("group_id",0);
            $package_id = $this->_post("package_id",0);
            $order_code = $this->_post("order_code",0,"缺少订单编号");
            $score   = $this->_post("score",'',"缺少评分");
            $escore  = $this->_post("express_score",''); //物流服务
            $dscore  = $this->_post("delivery_score",'');//发货速度
            $sscore  = $this->_post("service_score",''); //服务态度
            $comment = $_POST['_data_comment'];
 
            //检查字段
            if(!is_array($comment)) $this->apiReturnErr('非法评价');
            //判断订单状态
            $result = apiCall(OrdersApi::GET_INFO,[['order_code'=>$order_code,'uid'=>$uid]]);
            if(!$result['status']) $this->apiReturnErr($result['info']);
            if(empty($result['info'])) $this->apiReturnErr('无此订单');
            if($result['info']['comment_status'] != Orders::ORDER_TOBE_EVALUATE){
                $this->apiReturnErr('订单已评');
            }
            if($result['info']['pay_status'] == Orders::ORDER_TOBE_PAID){
                $this->apiReturnErr('订单未支付');
            }

            //过滤评价内容数组
            $comment = $this->commentFilter($comment);
            $attachment = $this->_post("attachments",'');
            $pids        = explode(',', $pid);
            $psku_ids    = explode(',', $psku_id);
            $group_ids   = explode(',', $group_id);
            $package_ids = explode(',', $package_id);
            $len  = count($pids);
            $scores  = explode(',', $score);
            $escores = explode(',', $escore);
            $dscores = explode(',', $dscore);
            $sscores = explode(',', $sscore);
            $attachments = explode(',', $attachment); //注意 ：永不为空

            if(($attachment && $len != count($attachments)) || $len != count($scores) || $len!=count($comment) || $len != count($psku_ids) || $len != count($group_ids) || $len != count($package_ids))
            $this->apiReturnErr('数据不匹配');
            //检查订单item

            $r = apiCall(OrdersItemApi::CHECK_ORDER_ITEM,[$order_code,$pids,$psku_ids,$group_ids,$package_ids]);
            if(!$r['status']) $this->apiReturnErr($r['info']);
            //开启事务
            $model = new \think\model\Adv();
            $model ->startTrans();
            foreach ($pids as $k => $v) {
                $psku_id    = $psku_ids[$k];
                $group_id   = $group_ids[$k];
                $package_id = $package_ids[$k];
                // 是否评价过 - 以防万一
                $result = apiCall(OrderCommentApi::GET_INFO,[['product_id'=>$v,'order_code'=>$order_code,'user_id'=>$uid,'psku_id'=>$psku_id,'group_id'=>$group_id,'package_id'=>$package_id],'createtime desc']);
                if(!$result['status']){
                    $model->rollback();
                    $this->apiReturnErr($result['info']);
                }
                if(!empty($result['info'])){
                    $model->rollback();
                    $this->apiReturnErr('您已经评价过此单的某个商品');
                }

                $comm = $comment[$k];
                if(empty($comm)){
                    $model->rollback();
                    $this->apiReturnErr('评价:null');
                }
                $score = $scores[$k];
                if($score<0 || $score>5) $score=0;
                // $score = number_format($score,2);
                if(is_array($escores) && isset($escores[$k])) $escore = $escores[$k];
                else $escore=5;
                if($escore<0 || $escore>5) $escore=0;
                if(is_array($dscores) && isset($dscores[$k])) $dscore = $dscores[$k];
                else $dscore=5;
                if($dscore<0 || $dscore>5) $dscore=0;
                if(is_array($sscores) && isset($sscores[$k])) $sscore = $sscores[$k];
                else $sscore=5;
                if($sscore<0 || $sscore>5) $sscore=0;

                $entity = [
                    'user_id'    =>$uid,
                    'order_code' =>$order_code,
                    'createtime' =>NOW_TIME,
                    'product_id' =>$pids[$k],
                    'score'      =>$score,
                    'logistics_service' =>$escore,
                    'delivery_speed'    =>$dscore,
                    'service_attitude'  =>$sscore,
                    'comment'    =>$comm,
                    'psku_id'    =>$psku_id,
                    'group_id'   =>$group_id,
                    'package_id' =>$package_id,
                ];
                $result = apiCall(OrderCommentApi::ADD,[$entity]);
                if(!$result['status']){
                    $model->rollback();
                    $this->apiReturnErr($result['info']);
                }
                // 添加附件
                $aid = explode('-',$attachments[$k]);
                // trace($aid);
                $dataList = [];
                $i = 0;
                foreach($aid as $vv){
                    $dataList[$i] = [
                        'pic_id'      => intval($vv),
                        'comment_id'  => intval($result['info']),
                        'upload_time' => NOW_TIME,
                    ];
                    $i++;
                }
                $result = apiCall(OrderCommentAttachsApi::ADD_ALL,[$dataList]);
                if(!$result['status']){
                    $model->rollback();
                    $this->apiReturnErr($result['info']);
                }
            }
            //更改订单评价状态
            $result = apiCall(OrdersApi::SAVE,[['order_code'=>$order_code,'uid'=>$uid],['comment_status'=>Orders::ORDER_HUMAN_EVALUATED]]);
            if(!$result['status']){
                $model->rollback();
                $this->apiReturnErr($result['info']);
            }
            $model->commit();
             // 推送消息
            $entity = [
                'from_id' =>0,
                'title'   =>Message::MESSAGE_ORDER,
                'content' =>'编号为'.$order_code.'的订单评价成功',
                'summary' =>'订单评价成功',
                'extra'   =>['uid'=>$uid], //消息记录中的
            ];
            $after_open = ['type'=>'go_activity','param'=>Message::MESSAGE_ORDER_ACTIVITY,'extra'=>['order_code'=>$order_code]]; //推送参数
            $r = apiCall(MessageApi::PUSH_MESSAGE_WITH_TYPE,[Message::MESSAGE_ORDER,$entity,$uid,false,$after_open]);
            if(!$r['status']) $this->apiReturnSuc($r['info']);
            $this->apiReturnSuc('评价成功');
        }
    }

    //新版 立即购买 不处理支付
    //返回实际支付金额
    public function addBySkuNew(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/addBySkuNew",$_GET,$_POST,"应用" . $this->client_id . "调用立即购买接口");
            $uid        = $this->_post("uid",0,"缺少用户ID");
            $pid        = $this->_post("pid","","pid缺失");
            $psku_id    = $this->_post("psku_id","","psku_id缺失");
            $count      = $this->_post("count",1);
            $group_id   = $this->_post("group_id",0);
            $package_id = $this->_post("package_id",0);
            $address_id = $this->_post("address_id","","缺失收货地址");
            $red_envelop_id = $this->_post("red_id","");    //红包ID
            $coupon_id  = $this->_post("coupon_id",""); //优惠券ID
            // $money      = $this->_post("money",0) ;    //钱包余额
            $note       = $this->_post("note","");      //备注
            $from       = $this->_post("from","");      //订单来源
            $pay_type   = 0;    //支付类型 1:支付宝
            $store_id   = 0;
            $red_envelop_id = intval($red_envelop_id);
            $package_id     = intval($package_id);
            $group_id       = intval($group_id);
            $coupon_id      = intval($coupon_id);
            $count    = max(intval($count),1);
            $pids     = explode(',', $pid);
            $psku_ids = array_unique(explode(',', $psku_id));
            if(count($pids) != count($psku_ids)) $this->apiReturnErr('参数不匹配');
             //1.1检查收货地址 - 计算运费准备
            if(empty($address_id)) $this->apiReturnErr('收货地址缺失');
            $r = apiCall(AddressApi::GET_INFO,[['id'=>$address_id]]);
            $this->checkApiCallResult($r,true,'收货地址错误');
            $address_info = $r['info']; //地址信息
            // unset($address_info['id']);
            //2.检查用户可用余额
            //3.查询商品信息
            //套餐检查
            if($package_id){
                $group_id = 0;$count = 1;
                $r = apiCall(ProductPackageItemApi::CHECK,[$pids,$psku_ids,$package_id]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
            }else{
                $package_id = 0;
                if(1 !== count($pids) || 1 !== count($psku_ids))
                    $this->apiReturnErr('非套餐只能添加单个商品');

            }
            //4.获取商品信息
            $pro_info = [];
            $total_tax = 0;
            foreach ($pids as $k=>$v) {
                $psku_id = $psku_ids[$k];
                $r = apiCall(ProductApi::GET_WITH_SKU,[$v,$psku_id,$uid,$group_id]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                if(!$store_id)  $store_id = intval($r['info']['store_id']);
                $pro_info[$v] = $r['info'];
                $pro_info[$v]['p_id']       = $pid;
                $pro_info[$v]['count']      = $count;
                $pro_info[$v]['package_id'] = $package_id;
                $pro_info[$v]['group_id']   = $group_id;
                $pro_info[$v]['psku_id']    = $psku_id;
                if(isset($r['info']['icon_url']) || empty($r['info']['icon_url'])){
                    //查询商品主图
                    $res = apiCall(ProductImageApi::GET_INFO,[['pid' => $v,'type'=> 6015]]);
                    $this->checkApiCallResult($res,true,'商品ID错误');
                    $pro_info[$v]['icon_url'] = $res['info']['img_id'];
                }
                //商品检查 - 限购 - 库存
                $r = apiCall(ProductSkuApi::CHECK_SKUID,[$uid,$psku_ids[$k],$count,false]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                //查询税费
                $r = apiCall(ProductSkuApi::GET_TAX,[$v,$psku_ids[$k]]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                $tax = floatval($r['info']);//税费;
                $pro_info[$v]['tax_rate'] = $tax;
                $total_tax += $tax*$count; //总税费

            }
            unset($res);
            $pro_info = array_values($pro_info);
            // trace('===pro_info');
            // trace($pro_info);
            //5.生成一个订单
            $now   = time();
            $model = new \think\model\Adv();
            $model ->startTrans();
            //5.1 预处理
            $free_shipping   = 0;  //是否包邮
            $entity          = $address_info;
            $entity['log']   = ''; //订单明细

            // $entity['items']      = $pro_info; //下面会加上套餐价格
            $entity['uid']        = $uid;
            $entity['order_code'] = getOrderid($uid);
            $entity['price']      = 0;   //订单总额(包含运费,不算优惠)
            // $post_price           = 0;//运费总额
            $entity['note']       = $note;
            // $entity['status']     = 1;//正常
            $entity['pay_status'] = 0;   //未付款
            $entity['order_status'] = 2; //待确认
            $entity['cs_status']  = 0;   //未售后
            $entity['createtime'] = $now;
            $entity['updatetime'] = $now;
            $entity['from']       = $from;
            $entity['idcode']     = '';  //店铺优惠码，暂未使用
            $discount_money       = 0;   //优惠金额 - 不包括运费
            $entity['storeid']    = $store_id;
            //tex_amount 0.00 税款金额
            $entity['tax_amount'] = $total_tax;
            //goods_amonut 0.00 货款
            $entity['goods_amount']   = 0;
            $entity['pay_type']       = $pay_type;
            $entity['pay_balance']    = 0;
            $entity['red_envelop_id'] = $red_envelop_id;
            $entity['coupon_id']      = $coupon_id;

            //5.2 计算运费
            $r = $this->getPostPrice($pro_info,$address_id,$uid);
            $this->checkApiReturn($r,false,false,$model);
            $post_price = floatval($r['info']);
            //5.3 计算商品价格
            //添加购物车时已做 - 有则使用使用会员价 - 次之
            //添加购物车时已做 - 有则使用活动价 - 优先
            //TODO  -  价格验证
            if($package_id){
                $r = apicall(ProductPackageApi::GET_INFO,[['id'=>$package_id],false,'package_price']);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                //上面套餐已检查 去掉？
                // if(empty($r['info'])) $this->apiReturnErr('套餐已失效');
                // if($r['info']['create_time']>time() || $r['info']['end_time']<time())
                //     return $this->apiReturnErr('套餐已过期');
                $price = floatval($r['info']['package_price']); //一个套餐时使用套餐价
                $pack_price = $price;
                $entity['log']  .= '套餐总额：'.$price;
            }else{
                $price = floatval($pro_info[0]['price'])*$count;//多个同规格商品时计算价格
                $pack_price = 0;
                $entity['log']  .= '商品总额：'.$price;
            }
            //+ package_price
            foreach ($pro_info as &$v) {
                $v['package_price'] = $pack_price;
            }
            unset($pack_price);
            $entity['items'] = $pro_info;
            // trace('===price:'.$price);
            $entity['price'] = $price;
            //5.4 检查红包 - 付款成功需要处理 ?
            if($red_envelop_id){
                $r = $this->useRedEnvelope($red_envelop_id,$uid,$price);
                $this->checkApiReturn($r,false,false,$model);
                $discount_money += floatval($r['info']);
                $entity['log'] .= '-红包：'.$r['info'];
            }
            //5.5 检查优惠券 - 付款成功需要处理 ?
            if($coupon_id){
                $r = $this->useCoupon($coupon_id,$uid,$price);
                $this->checkApiReturn($r,false,false,$model);
                $discount_money += floatval($r['info']);
                $entity['log'] .='-优惠券：'.$r['info'];
            }
            //5.6 店铺优惠
            $r = apiCall(StorePromotionApi::GET_INFO,[['store_id'=>$store_id]]);
            $this->checkApiReturn($r,false,false,$model);
            if(!empty($r['info'])){
                $Promotion = $r['info'];
                $now_time = time();
                if($Promotion['start_time']<= $now_time && $now_time <=$Promotion['end_time']){
                    //在活动期内
                    if($Promotion['condition'] <= $price){
                        $discount_money += floatval($Promotion['discount_money']);//满减优惠
                        $entity['log']  .= '-店铺优惠：'.$Promotion['discount_money'];
                        $free_shipping = $Promotion['free_shipping'];

                    }
                }
            }
            //5.7 商品总额检测
            $post_price = $free_shipping?0:$post_price;//该订单运费总额
            $entity['post_price'] = $post_price;
            $entity['discount_money'] = $discount_money;
            if($entity['price'] < $discount_money + 0.01){
                $model->rollback();
                $this->apiReturnErr("不允许优惠全部商品总额,至少为0.01元!");
            }
            //5.8 支付总额检查
            $entity['price'] += $post_price;
            $entity['log']  .= '+运费：'.$post_price;
            $pay = round($entity['price'] - $discount_money,2);
            if($pay < 0.01){
                // $model->rollback();
                // $this ->apiReturnErr("订单支付金额过低,至少为0.01元!");
                $pay = 0.01;
            }
            $entity['log']  .= '-支付总额:'.$pay;
            //5.9 实际支付检查
            //5.10 订单添加
            $r = apiCall(OrdersApi::ADD_ORDER,[$entity]);
            $this->checkApiReturn($r,false,false,$model);
            //6. 返回支付编号,用这个支付编号来生成支付信息
            $payCode = $r['info'];
            $info = $this->getPayReturnInfoNew($payCode.';',$uid,$pay);
            $model->commit();
            $this ->apiReturnSuc($info);
        }
    }

    //立即购买 -余额处理掉 -（单商品 或 套餐）
    // 订单总额 = 商品总额 + 运费
    // 优惠总额 = 红包 + 优惠券 + 店铺优惠
    // 支付总额 = 订单总额 - 优惠总额
    // 实际支付 = 支付总额 - 余额支付
    // 注1：运费为各商品运费之和
    // 注2：优惠全部相对于商品总额
    // 注3：商品总额>= 优惠总额+0.01
    // 注4：支付总额>= 0.01元
    // 注5：实际支付>= 0
    public function addBySku(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/addBySku",$_GET,$_POST,"应用" . $this->client_id . "调用立即购买接口");
            $uid        = $this->_post("uid",0,"缺少用户ID");
            $pid        = $this->_post("pid","","pid缺失");
            $psku_id    = $this->_post("psku_id","","psku_id缺失");
            $count      = $this->_post("count",1);
            $group_id   = $this->_post("group_id",0);
            $package_id = $this->_post("package_id",0);
            $address_id = $this->_post("address_id","","缺失收货地址");
            $red_envelop_id = $this->_post("red_id","");    //红包ID
            $coupon_id  = $this->_post("coupon_id",""); //优惠券ID
            $money      = $this->_post("money",0) ;    //钱包余额
            $note       = $this->_post("note","");      //备注
            $from       = $this->_post("from","");      //订单来源
            $pay_type   = 0;    //支付类型 1:支付宝
            $store_id   = 0;
            $red_envelop_id = intval($red_envelop_id);
            $package_id     = intval($package_id);
            $group_id       = intval($group_id);
            $coupon_id      = intval($coupon_id);
            $count    = max(intval($count),1);
            $pids     = explode(',', $pid);
            $psku_ids = array_unique(explode(',', $psku_id));
            if(count($pids) != count($psku_ids)) $this->apiReturnErr('参数不匹配');
             //1.1检查收货地址 - 计算运费准备
            if(empty($address_id)) $this->apiReturnErr('收货地址缺失');
            $r = apiCall(AddressApi::GET_INFO,[['id'=>$address_id]]);
            $this->checkApiCallResult($r,true,'收货地址错误');
            $address_info = $r['info']; //地址信息
            // unset($address_info['id']);
            //2.检查用户可用余额
            $money = round(floatval($money),2);
            if($money>0){
                $r = apiCall(WalletApi::CHECK_USER_MONEY,[$uid,$money]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
            }elseif($money<0){
                $this->apiReturnErr("余额错误!");
            }
            //3.查询商品信息
            //套餐检查
            if($package_id){
                $group_id = 0;$count = 1;
                $r = apiCall(ProductPackageItemApi::CHECK,[$pids,$psku_ids,$package_id]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
            }else{
                $package_id = 0;
                if(1 !== count($pids) || 1 !== count($psku_ids))
                    $this->apiReturnErr('非套餐只能添加单个商品');

            }
            //4.获取商品信息
            $pro_info = [];
            $total_tax = 0;
            foreach ($pids as $k=>$v) {
                $psku_id = $psku_ids[$k];
                $r = apiCall(ProductApi::GET_WITH_SKU,[$v,$psku_id,$uid,$group_id]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                if(!$store_id)  $store_id = intval($r['info']['store_id']);
                $pro_info[$v] = $r['info'];
                $pro_info[$v]['p_id']       = $pid;
                $pro_info[$v]['count']      = $count;
                $pro_info[$v]['package_id'] = $package_id;
                $pro_info[$v]['group_id']   = $group_id;
                $pro_info[$v]['psku_id']    = $psku_id;
                if(isset($r['info']['icon_url']) || empty($r['info']['icon_url'])){
                    //查询商品主图
                    $res = apiCall(ProductImageApi::GET_INFO,[['pid' => $v,'type'=> 6015]]);
                    $this->checkApiCallResult($res,true,'商品ID错误');
                    $pro_info[$v]['icon_url'] = $res['info']['img_id'];
                }
                //商品检查 - 限购 - 库存
                $r = apiCall(ProductSkuApi::CHECK_SKUID,[$uid,$psku_ids[$k],$count,false]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                //查询税费
                $r = apiCall(ProductSkuApi::GET_TAX,[$v,$psku_ids[$k]]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                $tax = floatval($r['info']);//税费;
                $pro_info[$v]['tax_rate'] = $tax;
                $total_tax += $tax*$count; //总税费

            }
            unset($res);
            $pro_info = array_values($pro_info);
            // trace('===pro_info');
            // trace($pro_info);
            //5.生成一个订单
            $now   = time();
            $model = new \think\model\Adv();
            $model ->startTrans();
            //5.1 预处理
            $free_shipping   = 0;  //是否包邮
            $entity          = $address_info;
            $entity['log']   = ''; //订单明细

            // $entity['items']      = $pro_info; //下面会加上套餐价格
            $entity['uid']        = $uid;
            $entity['order_code'] = getOrderid($uid);
            $entity['price']      = 0;   //订单总额(包含运费,不算优惠)
            // $post_price           = 0;//运费总额
            $entity['note']       = $note;
            // $entity['status']     = 1;//正常
            $entity['pay_status'] = 0;   //未付款
            $entity['order_status'] = 2; //待确认
            $entity['cs_status']  = 0;   //未售后
            $entity['createtime'] = $now;
            $entity['updatetime'] = $now;
            $entity['from']       = $from;
            $entity['idcode']     = '';  //店铺优惠码，暂未使用
            $discount_money       = 0;   //优惠金额 - 不包括运费
            $entity['storeid']    = $store_id;
            //tex_amount 0.00 税款金额
            $entity['tax_amount'] = $total_tax;
            //goods_amonut 0.00 货款
            $entity['goods_amount']   = 0;
            $entity['pay_type']       = $pay_type;
            $entity['pay_balance']    = 0;
            $entity['red_envelop_id'] = $red_envelop_id;
            $entity['coupon_id']      = $coupon_id;

            //5.2 计算运费
            $r = $this->getPostPrice($pro_info,$address_id,$uid);
            $this->checkApiReturn($r,false,false,$model);
            $post_price = floatval($r['info']);
            //5.3 计算商品价格
            //添加购物车时已做 - 有则使用使用会员价 - 次之
            //添加购物车时已做 - 有则使用活动价 - 优先
            //TODO  -  价格验证
            if($package_id){
                $r = apicall(ProductPackageApi::GET_INFO,[['id'=>$package_id],false,'package_price']);
                if(!$r['status']) $this->apiReturnErr($r['info']);
                //上面套餐已检查 去掉？
                // if(empty($r['info'])) $this->apiReturnErr('套餐已失效');
                // if($r['info']['create_time']>time() || $r['info']['end_time']<time())
                //     return $this->apiReturnErr('套餐已过期');
                $price = floatval($r['info']['package_price']); //一个套餐时使用套餐价
                $pack_price = $price;
                $entity['log']  .= '套餐总额：'.$price;
            }else{
                $price = floatval($pro_info[0]['price'])*$count;//多个同规格商品时计算价格
                $pack_price = 0;
                $entity['log']  .= '商品总额：'.$price;
            }
            //+ package_price
            foreach ($pro_info as &$v) {
                $v['package_price'] = $pack_price;
            }
            unset($pack_price);
            $entity['items'] = $pro_info;
            // trace('===price:'.$price);
            $entity['price'] = $price;
            //5.4 检查红包 - 付款成功需要处理 ?
            if($red_envelop_id){
                $r = $this->useRedEnvelope($red_envelop_id,$uid,$price);
                $this->checkApiReturn($r,false,false,$model);
                $discount_money += floatval($r['info']);
                $entity['log'] .= '-红包：'.$r['info'];
            }
            //5.5 检查优惠券 - 付款成功需要处理 ?
            if($coupon_id){
                $r = $this->useCoupon($coupon_id,$uid,$price);
                $this->checkApiReturn($r,false,false,$model);
                $discount_money += floatval($r['info']);
                $entity['log'] .='-优惠券：'.$r['info'];
            }
            //5.6 店铺优惠
            $r = apiCall(StorePromotionApi::GET_INFO,[['store_id'=>$store_id]]);
            $this->checkApiReturn($r,false,false,$model);
            if(!empty($r['info'])){
                $Promotion = $r['info'];
                $now_time = time();
                if($Promotion['start_time']<= $now_time && $now_time <=$Promotion['end_time']){
                    //在活动期内
                    if($Promotion['condition'] <= $price){
                        $discount_money += floatval($Promotion['discount_money']);//满减优惠
                        $entity['log']  .= '-店铺优惠：'.$Promotion['discount_money'];
                        $free_shipping = $Promotion['free_shipping'];

                    }
                }
            }
            //5.7 商品总额检测
            $post_price = $free_shipping?0:$post_price;//该订单运费总额
            $entity['post_price'] = $post_price;
            $entity['discount_money'] = $discount_money;
            if($entity['price'] < $discount_money + 0.01){
                $model->rollback();
                $this->apiReturnErr("不允许优惠全部商品总额,至少为0.01元!");
            }
            //5.8 支付总额检查
            $entity['price'] += $post_price;
            $entity['log']  .= '+运费：'.$post_price;
            $pay = round($entity['price'] - $discount_money,2);
            if($pay < 0.01){
                // $model->rollback();
                // $this ->apiReturnErr("订单支付金额过低,至少为0.01元!");
                $pay = 0.01;
            }
            $entity['log']  .= '-支付总额:'.$pay;
            //5.9 实际支付检查
            if($money>0){
                if($money>$pay)  $money = $pay;
                $entity['pay_balance'] = $money;
                $entity['log']  .= '-钱包：'.$money;
                //用户余额减少 + 记录
                $r = apiCall(WalletApi::MINUS,[$uid,$money,getDatatree('wallet_pay_goods'),'余额支付']);
                $this->checkApiReturn($r,false,false,$model);
            }elseif($money<0){
                $model->rollback();
                $this->apiReturnErr("余额错误!");
            }
            //5.10 订单添加
            $r = apiCall(OrdersApi::ADD_ORDER,[$entity]);
            $this->checkApiReturn($r,false,false,$model);
            //6. 返回支付编号,用这个支付编号来生成支付信息
            $payCode = $r['info'];
            $ordersPayCode = [
                'order_content' => $payCode.';',
                'createtime'    => $now,
                'uid'           => $uid,
                'pay_type'      => $pay_type,
                'pay_money'     => $pay,
                'pay_code'      => '',
                'pay_balance'   => $money,
                'pay_status'    => 0,
            ];

            $r    = apiCall(OrdersPaycodeApi::ADD,[$ordersPayCode]);
            $this ->checkApiReturn($r,false,false,$model);
            $info = $this->getPayReturnInfo($r['info'],$uid,$pay-$money);
            //
            if($pay === $money){
                //本次支付无需第三方支付
                //查询订单信息
                $pay_type = 3;
                //本次支付状态
                $r = apiCall(OrdersPaycodeApi::SAVE,[['order_content'=>$payCode.';'],['pay_type'=>$pay_type,'pay_status'=>1,'order_status'=>2]]);
                $this->checkApiReturn($r,false,'未知错误:payCode save 0',$model);
                //该单完全由余额支付
                $r = apiCall(OrderStatusApi::PAY_ORDER,[$info['code'],$payCode,$uid,$pay_type]);
                $this->checkApiReturn($r,false,false,$model);
            }
            $model->commit();
            $this ->apiReturnSuc($info); //全余额是 total_price=0,client注意判断
        }
    }
    /**
     * 订单添加
     * 优惠使用： 在订单总额上使用(现) -- (在上次优惠后总额上使用？)
     */
    public function add(){
        if(IS_POST){
            $this->checkVersion(101);
            addLog("Orders/add",$_GET,$_POST,"应用" . $this->client_id . "调用订单添加接口");
            $uid        = $this->_post("uid",0,"缺少用户ID");
            $cart_ids_a = $this->_post("cart_ids","","购物车信息缺失");
            $address_id = $this->_post("address_id","","缺失收货地址");
            $red_envelop_ids = $this->_post("red_ids",""); //红包ID
            $coupon_ids = $this->_post("coupon_ids",""); //优惠券ID
            $money      = $this->_post("money","");     //钱包余额 1:1
            $notes      = $_POST['_data_notes'];//I('post.note',[],NULL);//$this->_post("note","");
            if(empty($notes)) $notes = [];
            $from       = $this->_post("from",""); //订单来源
            $pay_type   = 0; //支付类型 1:支付宝(+余额),2:微信(+余额),3:余额
            //1.参数检测
            $arr_cart_ids_a = explode(',', $cart_ids_a);
            $store_num      = count($arr_cart_ids_a);
            if($red_envelop_ids){
                $red_envelop_ids = array_unique(explode(',', $red_envelop_ids));
                if($store_num != count($red_envelop_ids)) $this->apiReturnErr('参数不匹配');
            }
            if($coupon_ids){
                $coupon_ids = array_unique(explode(',', $coupon_ids));
                if($store_num != count($coupon_ids)) $this->apiReturnErr('参数不匹配');
            }
            if($notes && is_array($notes)){
                if(count($notes) != $store_num) $this->apiReturnErr('参数不匹配');
            }
            //1.1检查收货地址 - 计算运费准备
            if(empty($address_id)) $this->apiReturnErr('收货地址缺失');
            $r = apiCall(AddressApi::GET_INFO,[['id'=>$address_id]]);
            $this->checkApiCallResult($r,true,'收货地址错误');
            $address_info = $r['info']; //地址信息
            unset($address_info['id']);
            //2.检查用户可用余额
            $money = round(floatval($money),2);
            $money_bak = $money;
            if($money>0){
                $r = apiCall(WalletApi::CHECK_USER_MONEY,[$uid,$money]);
                if(!$r['status']) $this->apiReturnErr($r['info']);
            }elseif($money<0){
                $this->apiReturnErr('余额错误:1<0');
            }
            //3.一次查询所有购物车信息
            $str_cartids_a = str_replace('-', ',', $cart_ids_a);
            $map = [
                'cart.`uid`' =>$uid,
                '_string'  =>' cart.`id` in ('.$str_cartids_a.')',
            ];
            // $r = apiCall(ShoppingCartApi::QUERY_NO_PAGING,[$map]);
            $r = apiCall(ShoppingCartApi::QUERY_WITH_STORE,[$map]);
            $this ->checkApiCallResult($r,true,"购物车里没有商品哦!");
            $carts_all = []; //cart_id 排序购物车
            $store_ids = [];
            foreach ($r['info'] as $v) {
                $carts_all[$v['id']] = $v;
                $store_ids[] = intval($v['store_id']);
            }
            if($store_num !== count(array_unique($store_ids))) $this->apiReturnErr('店铺个数不匹配');
            //4.每个店铺生成一个订单
            $now = time();
            $payCode     = "";// "pay_code1;pay_code2;..."
            $total_price = 0;
            // $total_tax   = 0;
            $model = new \think\model\Adv();
            $model->startTrans();
            $is_all_money = [];
            foreach($arr_cart_ids_a as $k => $str_cart_ids){
                //4.1 第k+1 个店铺
                $arr_cart_ids = array_unique(explode('-', $str_cart_ids));
                $str_cart_ids = str_replace('-', ',', $arr_cart_ids);
                $carts_info   = [];
                $store_id     = 0;
                //4.2 检查购物车 限购 和库存
                //重复:同商品不同规格的话检查了多次，
                //可换用shop/ProductSkuApi/checkSkuID
                //但不全部检查的话错误信息怎么处理？
                foreach ($arr_cart_ids as $cart_id) {
                    $r  = apiCall(ShoppingCartApi::CHECK_ID,[$cart_id,0,true]);
                    $this->checkApiReturn($r,false,false,$model);
                    $carts_info[$cart_id] = $carts_all[$cart_id];
                    if(0===$store_id){
                        $store_id = intval($carts_all[$cart_id]['store_id']);
                    }else{
                        if($store_id !== intval($carts_all[$cart_id]['store_id']))
                        {
                            $model->rollback();
                            $this->apiReturnErr('impossible:each-order-multi-store');
                        }
                    }
                }
                //4.3 预处理 
                $red_envelop_id  = $red_envelop_ids ? $red_envelop_ids[$k]:'';
                $coupon_id       = $coupon_ids ? $coupon_ids[$k]:'';
                $free_shipping   = 0; //是否包邮
                $entity          = $address_info;
                // $entity['items'] = $carts_info; //下面会加上套餐价格
                $entity['log']   = ''; //订单明细
                $price           = 0; //订单总额，不含运费

                $entity['uid']        = $uid;
                $entity['order_code'] = getOrderid($uid);
                $entity['price']      = 0;//订单总额(包含运费,不算优惠)
                $post_price           = 0;//运费总额
                $entity['note']       = $notes ? $notes[$k] :'';
                // $entity['status']     = 1;   //正常
                $entity['pay_status'] = 0;   //未付款
                $entity['order_status'] = 2; //待确认
                $entity['cs_status']  = 0;   //未售后
                $entity['createtime'] = $now;
                $entity['updatetime'] = $now;
                $entity['from']       = $from;
                $entity['idcode']     = '';//店铺优惠码，暂未使用
                $discount_money       = 0; //优惠金额
                $entity['storeid']    = $store_id;
                //tex_amount 0.00 税款金额
                $entity['tax_amount'] = 0.00; //下面计算
                //goods_amonut 0.00 货款
                $entity['goods_amount']   = 0.00;
                $entity['pay_type']       = $pay_type;
                $entity['pay_balance']    = 0;
                $entity['red_envelop_id'] = $red_envelop_id;
                $entity['coupon_id']      = $coupon_id;

                //4.4 计算店铺运费
                //商品根据pid分组
                $p_carts = [];
                foreach ($carts_info as $v) {
                    $p_carts[$v['p_id']][] = $v;
                }
                $packs = [];
                //计算总运费 - 已验证收货地址
                foreach($p_carts as $v){
                    $r = $this->getPostPrice($v,$address_id,$uid);
                    $this->checkApiReturn($r,false,false,$model);
                    $post_price = $post_price + floatval($r['info']);
                }
                //下继续 优惠后运费 
                //4.5 计算商品价格
                //添加购物车时已做 - 有则使用使用会员价 - 次之
                //添加购物车时已做 - 有则使用活动价 - 优先
                //TODO  -  购物车价格验证
                foreach ($carts_info as $v) {
                    $pack_id = intval($v['package_id']);
                    if($pack_id){
                        $create_time = intval($v['create_time']);
                        $packs[$pack_id][$create_time][$v['id']] = $v;
                        //TODO  套餐完整性 验证
                        //return 套餐不完整
                    }else{
                        $price += floatval($v['price'])*intval($v['count']);
                    }
                    $entity['tax_amount'] += intval($v['count'])*floatval($v['tax_rate']);
                    // trace('===price:'.$price);
                }
                // $total_tax +=$entity['tax_amount'];
                //加上套餐价格
                $packs_info = [];
                foreach ($packs as $k=>$v) {
                    $r = apiCall(ProductPackageApi::GET_INFO,[['id'=>$k],false,'package_price']);
                    // trace('===r');
                    // trace($r);
                    $this->checkApiReturn($r,false,'套餐已失效',$model);
                    foreach ($v as $vv) {
                        $pack_price = floatval($r['info']['package_price']);
                        $price += $pack_price;
                        $packs_info[$k] = $pack_price;
                    }
                }
                unset($packs);
                // carts_info  + package_price
                foreach ($carts_info as &$v) {
                    $pack_id = intval($v['package_id']);
                    if($pack_id){
                        $v['package_price'] = $packs_info[$pack_id];
                    }else{
                        $v['package_price'] = 0;
                    }
                }
                unset($packs_info);
                $entity['items'] = $carts_info;
                $entity['log']  .= ';总额(不含运费和优惠)：'.$price;
                //4.6 检查红包 - 付款成功需要处理 ?
                if($red_envelop_ids && isset($red_envelop_ids[$k])){
                    $r = $this->useRedEnvelope($red_envelop_ids[$k],$uid,$price);
                    $this->checkApiReturn($r,false,false,$model);
                    $discount_money += floatval($r['info']);
                    $entity['log'] .= '-红包：'.$r['info'];
                }
                //4.7 检查优惠券 - 付款成功需要处理 ?
                if($coupon_ids && isset($coupon_ids[$k])){
                    $r = $this->useCoupon($coupon_ids[$k],$uid,$price);
                    $this->checkApiReturn($r,false,false,$model);
                    $discount_money += floatval($r['info']);
                    $entity['log'] .='-优惠券：'.$r['info'];
                }
                //4.8 店铺优惠
                $r = apiCall(StorePromotionApi::GET_INFO,[['store_id'=>$store_id]]);
                $this->checkApiReturn($r,false,false,$model);
                if(!empty($r['info'])){
                    $Promotion = $r['info'];
                    $now_time = time();
                    if($Promotion['start_time']<= $now_time && $now_time <=$Promotion['end_time']){
                        //在活动期内
                        if($Promotion['condition'] <= $price){
                            $discount_money += floatval($Promotion['discount_money']);//满减优惠
                            $entity['log']  .= '-店铺优惠：'.$Promotion['discount_money'];
                            $free_shipping = $Promotion['free_shipping'];

                        }
                    }
                }
                //4.9 商品总额检测 且 不允许支付0元及以下
                $post_price = $free_shipping ? 0 : $post_price;//该订单运费总额
                $entity['post_price'] = $post_price;
                $entity['discount_money'] = $discount_money; //该订单优惠总额
                $entity['log']  .= '+运费：'.$post_price;
                if($price - $discount_money < 0.01){
                    $model->rollback();
                    $this->apiReturnErr("优惠过多,优惠后商品总额至少为0.01元!");
                }
                //该订单总额，包含运费
                $entity['price'] = $price + $post_price; 
                //支付总额检测
                $pay = round($entity['price'] - $discount_money,2);
                if($pay < 0.01){
                    $pay = 0.01;
                    // $model->rollback();
                    // $this->apiReturnErr("订单支付金额过低,至少为0.01元!");
                }
                $entity['log']  .= '-支付总额:'.$pay;
                //4.10 使用钱包 代替全部或部分支付金额
                if($money>0){
                    //余额未用完
                    if($money >= $pay){
                        //余额足够支付
                        $entity['pay_balance'] = $pay;
                        $money -= $pay;
                    }else{
                        //余额部分支付
                        $entity['pay_balance'] = $money;
                        $money = 0;
                    }
                    $entity['log']  .= '-钱包：'.$entity['pay_balance'];
                }elseif($money<0){
                    $model->rollback();
                    $this->apiReturnErr("余额错误:2<0");
                }
                //4.11 实付金额检测 不允许支付0元及以下
                $realPay = floatval($pay - $entity['pay_balance']);
                if($realPay < 0){
                    //需要第三方支付
                    $model->rollback();
                    $this->apiReturnErr("订单实付金额过低,至少为0元!");
                }
                //4.13 订单添加
                $r = apiCall(OrdersApi::ADD_ORDER,[$entity]);
                $this->checkApiReturn($r,false,false,$model);
                $payCode .= $r['info'].";";
                // trace('===realPay:'.$realPay);
                if($realPay == 0){
                   $is_all_money[$r['info']] = 1;
                }else{
                   $is_all_money[$r['info']] = 0;
                }
                // trace('===');
                // trace($is_all_money);
                $total_price += $pay;
            }
            //5 剩余金额检测
            if($money<0){
                $model->rollback();
                $this->apiReturnErr('余额错误:3<0');
            }
            //用户余额减少 + 余额记录
            $pay_balance = $money_bak-$money;
            if($pay_balance>0){
                $r = apiCall(WalletApi::MINUS,[$uid,$pay_balance,getDatatree('wallet_pay_goods'),'余额支付']);
                $this->checkApiReturn($r,false,false,$model);
            }elseif($pay_balance<0){
                $model->rollback();
                $this->apiReturnErr('支付余额错误');
            }
            //6. 添加到订单之后，就该删除购物车的数据
            $r = $this->deleteFromShoppingCart($uid,$str_cartids_a);
            $this->checkApiReturn($r,false,false,$model);
            if(!$r['status']){
                LogRecord($r['info'],__FILE__.__LINE__);
                $model->rollback();
                $this->apiReturnErr($r['info']);
            }
            //7. 返回支付编号,用这个支付编号来生成支付信息
            $ordersPayCode = [
                'order_content' => $payCode,
                'createtime'    => $now,
                'uid'           => $uid,
                'pay_type'      => $pay_type,
                'pay_money'     => $total_price,
                'pay_code'      => '',
                'pay_balance'   => $pay_balance,
                'pay_status'    => 0,
            ];

            $r    = apiCall(OrdersPaycodeApi::ADD,[$ordersPayCode]);
            $this ->checkApiReturn($r,false,false,$model);
            $info = $this->getPayReturnInfo($r['info'],$uid,$total_price-$pay_balance);
            if($total_price === $pay_balance){
                //本次支付无需第三方支付
                //查询订单信息
                $pay_type = 3;
                //本次支付状态
                $r = apiCall(OrdersPaycodeApi::SAVE,[['order_content'=>$payCode],['pay_type'=>$pay_type,'pay_status'=>1,'order_status'=>2]]);
                $this->checkApiReturn($r,false,'未知错误:payCode save 0',$model);
            }
            // $order_codes = explode(';', $payCode);
            // trace('===.===');
            // trace($is_all_money);
            foreach ($is_all_money as $k=>$v) {
                if(1 === $v){
                    // trace($info['code'].'==='.$k.'==='.$uid);
                    //该单完全由余额支付
                    $r = apiCall(OrderStatusApi::PAY_ORDER,[$info['code'],$k,$uid,2]);
                    $this->checkApiReturn($r,false,false,$model);
                }
            }
            $model->commit();
            $this ->apiReturnSuc($info);
        }else{
            $this->apiReturnErr('只支持post请求');
        }
    }
    /**
     * 订单添加 - 新版
     * 优惠使用： 在订单总额上使用(现) -- (在上次优惠后总额上使用？)
     */
    public function addNew(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/addNew",$_GET,$_POST,"应用" . $this->client_id . "调用订单添加接口");
            $uid        = $this->_post("uid",0,"缺少用户ID");
            $cart_ids_a = $this->_post("cart_ids","","购物车信息缺失");
            $address_id = $this->_post("address_id","","缺失收货地址");
            $red_envelop_ids = $this->_post("red_ids",""); //红包ID
            $coupon_ids = $this->_post("coupon_ids",""); //优惠券ID
            // $money      = $this->_post("money","");     //钱包余额 1:1
            $notes      = $_POST['_data_notes'];//I('post.note',[],NULL);//$this->_post("note","");
            if(empty($notes)) $notes = [];
            $from       = $this->_post("from",""); //订单来源
            $pay_type   = 0; //支付类型 1:支付宝(+余额),2:微信(+余额),3:余额
            //1.参数检测
            $arr_cart_ids_a = explode(',', $cart_ids_a);
            $store_num      = count($arr_cart_ids_a);
            if($red_envelop_ids){
                $red_envelop_ids = array_unique(explode(',', $red_envelop_ids));
                if($store_num != count($red_envelop_ids)) $this->apiReturnErr('参数不匹配');
            }
            if($coupon_ids){
                $coupon_ids = array_unique(explode(',', $coupon_ids));
                if($store_num != count($coupon_ids)) $this->apiReturnErr('参数不匹配');
            }
            if($notes && is_array($notes)){
                if(count($notes) != $store_num) $this->apiReturnErr('参数不匹配');
            }
            //1.1检查收货地址 - 计算运费准备
            if(empty($address_id)) $this->apiReturnErr('收货地址缺失');
            $r = apiCall(AddressApi::GET_INFO,[['id'=>$address_id]]);
            $this->checkApiCallResult($r,true,'收货地址错误');
            $address_info = $r['info']; //地址信息
            unset($address_info['id']);
            //2.检查用户可用余额
            //3.一次查询所有购物车信息
            $str_cartids_a = str_replace('-', ',', $cart_ids_a);
            $map = [
                'cart.`uid`' =>$uid,
                '_string'  =>' cart.`id` in ('.$str_cartids_a.')',
            ];
            // $r = apiCall(ShoppingCartApi::QUERY_NO_PAGING,[$map]);
            $r = apiCall(ShoppingCartApi::QUERY_WITH_STORE,[$map]);
            $this ->checkApiCallResult($r,true,"购物车里没有商品哦!");
            $carts_all = []; //cart_id 排序购物车
            $store_ids = [];
            foreach ($r['info'] as $v) {
                $carts_all[$v['id']] = $v;
                $store_ids[] = intval($v['store_id']);
            }
            if($store_num !== count(array_unique($store_ids))) $this->apiReturnErr('店铺个数不匹配');
            //4.每个店铺生成一个订单
            $now = time();
            $payCode     = "";// "pay_code1;pay_code2;..."
            $total_price = 0;
            // $total_tax   = 0;
            $model = new \think\model\Adv();
            $model->startTrans();
            $is_all_money = [];
            foreach($arr_cart_ids_a as $k => $str_cart_ids){
                //4.1 第k+1 个店铺
                $arr_cart_ids = array_unique(explode('-', $str_cart_ids));
                $str_cart_ids = str_replace('-', ',', $arr_cart_ids);
                $carts_info   = [];
                $store_id     = 0;
                //4.2 检查购物车 限购 和库存
                //重复:同商品不同规格的话检查了多次，
                //可换用shop/ProductSkuApi/checkSkuID
                //但不全部检查的话错误信息怎么处理？
                foreach ($arr_cart_ids as $cart_id) {
                    $r  = apiCall(ShoppingCartApi::CHECK_ID,[$cart_id,0,true]);
                    $this->checkApiReturn($r,false,false,$model);
                    $carts_info[$cart_id] = $carts_all[$cart_id];
                    if(0===$store_id){
                        $store_id = intval($carts_all[$cart_id]['store_id']);
                    }else{
                        if($store_id !== intval($carts_all[$cart_id]['store_id']))
                        {
                            $model->rollback();
                            $this->apiReturnErr('impossible:each-order-multi-store');
                        }
                    }
                }
                //4.3 预处理 
                $red_envelop_id  = $red_envelop_ids ? $red_envelop_ids[$k]:'';
                $coupon_id       = $coupon_ids ? $coupon_ids[$k]:'';
                $free_shipping   = 0; //是否包邮
                $entity          = $address_info;
                // $entity['items'] = $carts_info; //下面会加上套餐价格
                $entity['log']   = ''; //订单明细
                $price           = 0; //订单总额，不含运费

                $entity['uid']        = $uid;
                $entity['order_code'] = getOrderid($uid);
                $entity['price']      = 0;//订单总额(包含运费,不算优惠)
                $post_price           = 0;//运费总额
                $entity['note']       = $notes ? $notes[$k] :'';
                // $entity['status']     = 1;   //正常
                $entity['pay_status'] = 0;   //未付款
                $entity['order_status'] = 2; //待确认
                $entity['cs_status']  = 0;   //未售后
                $entity['createtime'] = $now;
                $entity['updatetime'] = $now;
                $entity['from']       = $from;
                $entity['idcode']     = '';//店铺优惠码，暂未使用
                $discount_money       = 0; //优惠金额
                $entity['storeid']    = $store_id;
                //tex_amount 0.00 税款金额
                $entity['tax_amount'] = 0.00; //下面计算
                //goods_amonut 0.00 货款
                $entity['goods_amount']   = 0.00;
                $entity['pay_type']       = $pay_type;
                $entity['pay_balance']    = 0;
                $entity['red_envelop_id'] = $red_envelop_id;
                $entity['coupon_id']      = $coupon_id;

                //4.4 计算店铺运费
                //商品根据pid分组
                $p_carts = [];
                foreach ($carts_info as $v) {
                    $p_carts[$v['p_id']][] = $v;
                }
                $packs = [];
                //计算总运费 - 已验证收货地址
                foreach($p_carts as $v){
                    $r = $this->getPostPrice($v,$address_id,$uid);
                    $this->checkApiReturn($r,false,false,$model);
                    $post_price = $post_price + floatval($r['info']);
                }
                //下继续 优惠后运费 
                //4.5 计算商品价格
                //添加购物车时已做 - 有则使用使用会员价 - 次之
                //添加购物车时已做 - 有则使用活动价 - 优先
                //TODO  -  购物车价格验证
                foreach ($carts_info as $v) {
                    $pack_id = intval($v['package_id']);
                    if($pack_id){
                        $create_time = intval($v['create_time']);
                        $packs[$pack_id][$create_time][$v['id']] = $v;
                        //TODO  套餐完整性 验证
                        //return 套餐不完整
                    }else{
                        $price += floatval($v['price'])*intval($v['count']);
                    }
                    $entity['tax_amount'] += intval($v['count'])*floatval($v['tax_rate']);
                    // trace('===price:'.$price);
                }
                // $total_tax +=$entity['tax_amount'];
                //加上套餐价格
                $packs_info = [];
                foreach ($packs as $k=>$v) {
                    $r = apiCall(ProductPackageApi::GET_INFO,[['id'=>$k],false,'package_price']);
                    // trace('===r');
                    // trace($r);
                    $this->checkApiReturn($r,false,'套餐已失效',$model);
                    foreach ($v as $vv) {
                        $pack_price = floatval($r['info']['package_price']);
                        $price += $pack_price;
                        $packs_info[$k] = $pack_price;
                    }
                }
                unset($packs);
                // carts_info  + package_price
                foreach ($carts_info as &$v) {
                    $pack_id = intval($v['package_id']);
                    if($pack_id){
                        $v['package_price'] = $packs_info[$pack_id];
                    }else{
                        $v['package_price'] = 0;
                    }
                }
                unset($packs_info);
                $entity['items'] = $carts_info;
                $entity['log']  .= ';总额(不含运费和优惠)：'.$price;
                //4.6 检查红包 - 付款成功需要处理 ?
                if($red_envelop_ids && isset($red_envelop_ids[$k])){
                    $r = $this->useRedEnvelope($red_envelop_ids[$k],$uid,$price);
                    $this->checkApiReturn($r,false,false,$model);
                    $discount_money += floatval($r['info']);
                    $entity['log'] .= '-红包：'.$r['info'];
                }
                //4.7 检查优惠券 - 付款成功需要处理 ?
                if($coupon_ids && isset($coupon_ids[$k])){
                    $r = $this->useCoupon($coupon_ids[$k],$uid,$price);
                    $this->checkApiReturn($r,false,false,$model);
                    $discount_money += floatval($r['info']);
                    $entity['log'] .='-优惠券：'.$r['info'];
                }
                //4.8 店铺优惠
                $r = apiCall(StorePromotionApi::GET_INFO,[['store_id'=>$store_id]]);
                $this->checkApiReturn($r,false,false,$model);
                if(!empty($r['info'])){
                    $Promotion = $r['info'];
                    $now_time = time();
                    if($Promotion['start_time']<= $now_time && $now_time <=$Promotion['end_time']){
                        //在活动期内
                        if($Promotion['condition'] <= $price){
                            $discount_money += floatval($Promotion['discount_money']);//满减优惠
                            $entity['log']  .= '-店铺优惠：'.$Promotion['discount_money'];
                            $free_shipping = $Promotion['free_shipping'];

                        }
                    }
                }
                //4.9 商品总额检测 且 不允许支付0元及以下
                $post_price = $free_shipping ? 0 : $post_price;//该订单运费总额
                $entity['post_price'] = $post_price;
                $entity['discount_money'] = $discount_money; //该订单优惠总额
                $entity['log']  .= '+运费：'.$post_price;
                if($price - $discount_money < 0.01){
                    $model->rollback();
                    $this->apiReturnErr("优惠过多,优惠后商品总额至少为0.01元!");
                }
                //该订单总额，包含运费
                $entity['price'] = $price + $post_price; 
                //支付总额检测
                $pay = round($entity['price'] - $discount_money,2);
                if($pay < 0.01){
                    $pay = 0.01;
                    // $model->rollback();
                    // $this->apiReturnErr("订单支付金额过低,至少为0.01元!");
                }
                $entity['log']  .= '-支付总额:'.$pay;
                //4.10 使用钱包 代替全部或部分支付金额
                //4.11 实付金额检测 不允许支付0元及以下
                //4.12 订单添加
                $r = apiCall(OrdersApi::ADD_ORDER,[$entity]);
                $this->checkApiReturn($r,false,false,$model);
                $payCode .= $r['info'].";";
                $total_price += $pay;
            }
            //5 剩余金额检测
            //6. 添加到订单之后，就该删除购物车的数据
            $r = $this->deleteFromShoppingCart($uid,$str_cartids_a);
            $this->checkApiReturn($r,false,false,$model);
            if(!$r['status']){
                LogRecord($r['info'],__FILE__.__LINE__);
                $model->rollback();
                $this->apiReturnErr($r['info']);
            }
            //7. 返回支付编号,用这个支付编号来生成支付信息
            $info = $this->getPayReturnInfoNew($payCode,$uid,$total_price);
            $model->commit();
            $this ->apiReturnSuc($info);
        }else{
            $this->apiReturnErr('只支持post请求');
        }
    }
    /**
     * 查询订单详情
     */
    public function detail(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/detail",$_GET,$_POST,"应用" . $this->client_id . "调用查询订单详情接口");
            $id         = $this->_post('oid','');       //订单ID
            $order_code = $this->_post('order_code','');//订单 order_code
            if(!empty($id)){
                $map = ['id'=>$id];
            }elseif(empty($id) && !empty($order_code)){
                $map = ['order_code'=>$order_code];
            }else{
                $this->apiReturnErr('oid与order_code不得同时为空');
            }
            $result = apiCall(OrdersInfoViewApi::GET_INFO,[$map]);

            if($result['status']){
                $order = $result['info'];
                if(empty($order)){
                    $this->apiReturnErr("获取失败,没有此订单!");
                }
                // $order['store_logo_url'] = getImageUrl($order['store_logo']);
                if(empty($order['refund_time'])) $order['refund_time'] = '';
                if(empty($order['reason'])) $order['reason'] = '';
                if(empty($order['valid_status'])) $order['valid_status'] = '';
                if(empty($order['reply_msg'])) $order['reply_msg'] = '';
                $map = ['order_code'=>$order['order_code']];
                $result = apiCall(OrdersItemApi::QUERY_NO_PAGING,[$map]);
                if($result['status']){
                    // trace('---order---');
                    // trace($order);
                    $order['items'] = $result['info'];
                    $order['count'] = 0;
                    if(!empty($result['info'])){
                        foreach ($result['info'] as $v) {
                            $order['count'] = $order['count'] + $v['count'];
                        }
                    }
                    $order['count'] = ''.$order['count'];
                    // trace($order);
                    // $order['items'] = $this->convertDetail($result['info']);
                    // trace($order);
                }else {
                    $this->apiReturnErr($result['info']);
                }
                $this->apiReturnSuc($order);
            }else{
                $this->apiReturnErr($result['info']);
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }
    /**
     * 根据支付类型 - 生成支付信息
     * @return [type] [description]
     */
    public function rePay(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/rePay",$_GET,$_POST,"应用" . $this->client_id . "调用订单重新支付接口");

            $uid        = $this->_post("uid","","缺少用户ID");
            $order_code = $this->_post("order_code","","缺少订单编号");
            $map = [
                'uid'        =>$uid,
                'order_code' =>$order_code,
            ];
            $result = apiCall(OrdersApi::GET_INFO,[$map]);
            if(!$result['status']){
                LogRecord($result['info'],__FILE__.__LINE__);
                $this->apiReturnErr($result['info']);
            }
            // $this->apiReturnErr($result);
            if(empty($result['info'])) $this->apiReturnErr("订单ID非法!");
            $order    = $result['info'];
            if(intval($order['pay_status'])) $this->apiReturnErr('此订单已支付');
            // if(intval($result['createtime']) + 1800 <time()) $this->apiReturnErr('订单已过期');
            $total_price = round(floatval($order['price']) - floatval($order['discount_money']) - floatval($order['pay_balance']),2);
            if($total_price<=0) $this->apiReturnErr('订单错误:0=>待支付');
            $info = $this->getPayReturnInfoNew($order_code.';',$uid,$total_price);
            $this->apiReturnSuc($info);
        }else{
            $this->apiReturnErr('只支持post请求');
        }
    }
    /**
     * 生成第三方支付信息
     * @return [type] [description]
     */
    public function payNow(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/payNow",$_GET,$_POST,"应用" . $this->client_id . "调用订单确定支付接口");
            $uid        = $this->_post("uid","","缺少用户ID");
            $order_code = $this->_post("order_code","","缺少订单编号");
            $pay_type   = $this->_post("pay_type","","缺少类型");
            $money      = $this->_post("pay_money",0);
            $money      = (float)$money;
            $pay_type   = (int)$pay_type;
            if(!in_array($pay_type,[1,2,3])) $this->apiReturnErr('支付类型不支持');
            $pay_code    = '';
            $total_pay   = 0;
            $total_post  = 0;
            $total_need_pay   = 0;
            $real_pay_balance = 0;
            $now_pay_balance  = 0;
            $old_pay_balance  = 0;
            $str = ''; //wallet log note;
            //检查订单
            $order_codes = array_unique(explode(';', $order_code));
            array_pop($order_codes);
            // $order_str = '';
            // foreach ($$order_codes as $v) {
            //     $order_str .= ($order_str ? ',':'').'\''.$v.'\'';
            // }
            // trace('====');
            // trace($order_codes);
            $len = count($order_codes);
            $r = apiCall(OrdersApi::QUERY_NO_PAGING,[['uid'=>$uid,'_string'=>'order_code in (\''.implode('\',\'',$order_codes).'\')','status'=>1,'pay_status'=>0]]);
            $info = $r['info'];
            // if($order_code == '16243135412398255738;16243135412860199438;'){
            //     $this->apiReturnErr($info);
            // }
            if(!$r['status']) $this->apiReturnErr($info);
            if(empty($info) || $len != count($info)) $this->apiReturnErr('订单错误或不匹配');
            //检查余额
            if($money >0){
                $r = apiCall(WalletApi::CHECK_USER_MONEY,[$uid,$money]);
                if(!$r['info']) $this->apiReturnErr($r['info']);
            }
            if(3===$pay_type){
                $t = 0;
                foreach ($info as $v) {
                    $t += (float)$v['price'] - (float)$v['discount_money'] - (float)$v['pay_balance'];
                }
                if($money<$t) $this->apiReturnErr('余额不够支付,请搭配第三方支付');
            }
            $model = new \think\model\adv();
            $model ->startTrans();
            $has_money_pay = false;
            //循环订单
            foreach ($info as $v) {
                $order_code = $v['order_code'];
                $price      = (float)$v['price'];
                $balance    = (float)$v['pay_balance'];
                $discount   = (float)$v['discount_money'];
                $order_pay  = $price - $discount; //此订单支付总额
                $need_pay   = $order_pay - $balance; //此订单还需支付
                if($need_pay<=0) {
                    $model ->rollback();
                    $this->apiReturnErr('订单('.$order_code.')付款金额错误');
                }

                if($money>0){ //剩下余额>0
                    $pay_money = min($need_pay,$money);
                    $real_pay_balance +=$pay_money; //wallet用
                    $map = [
                        'pay_balance'=>$balance + $pay_money
                    ];
                    if($pay_money == $need_pay){
                        $str .= $order_code.'-'.$pay_money.'[ALL];';
                        $has_money_pay = true;
                        //此单支付完成 - 不参与支付
                        $map['pay_type']   = 3;
                        $map['pay_status'] = 1;
                        // $this->apiReturnErr($map);
                    }else{
                        $pay_code  .= $order_code.';';
                        $str .= $order_code.'-'.$pay_money.'[PAR];';
                        //此单还需支付
                        $total_pay += $order_pay;
                        $total_need_pay  += $need_pay;
                        $old_pay_balance += $balance;

                        $now_pay_balance += $pay_money;
                    }
                    $money -= $pay_money;//持有余额减少
                    //修改订单 订单支付余额增加
                    $r = apiCall(OrdersApi::SAVE,[['uid'=>$uid,'order_code'=>$order_code],$map]);
                    $this->checkApiReturn($r,false,'uid:'.$uid.'或order_code:'.$order_code.'错误',$model);
                }else{
                    $pay_code  .= $order_code.';';
                    $total_pay += $order_pay;
                    $total_need_pay  += $need_pay;
                    $old_pay_balance += $balance;
                }
            }
            //余额减少并记录
            // trace($real_pay_balance.'---'.$money);
            if($real_pay_balance >0 && $money >=0 ){
                $r = apiCall(WalletApi::MINUS,[$uid,$real_pay_balance,getDatatree('wallet_pay_goods'),'余额支付:'.$str]);
                $this->checkApiReturn($r,false,false,$model);
            }
            //7. 返回需要第三方支付的订单支付编号,用这个支付编号来生成支付信息
            if(!empty($pay_code)){
                $now = time();
                $ordersPayCode = [
                    'order_content' => $pay_code,
                    'createtime'    => $now,
                    'uid'           => $uid,
                    'pay_type'      => $pay_type,
                    'pay_money'     => $total_pay, //总支付金额
                    'pay_code'      => '',
                    'pay_balance'   => $now_pay_balance + $old_pay_balance,
                    'pay_status'    => 0,
                ];
                $r    = apiCall(OrdersPaycodeApi::ADD,[$ordersPayCode]);
                $this ->checkApiReturn($r,false,false,$model);
                $info = $this->getPayReturnInfo($r['info'],$uid,$total_pay-$now_pay_balance-$old_pay_balance);
                //根据支付类型返回支付信息
                $model ->commit();
                $this->apiReturnSuc(['pay_type'=>''.$pay_type,'pay_msg'=>$has_money_pay ? '部分支付完成,请尽快完成支付':'请尽快完成支付','pay_info'=>$info]);
            }else{
                $model ->commit();
                $this->apiReturnSuc(['pay_type'=>'3','pay_msg'=>'支付成功','pay_info'=>['temp'=>'']]);
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }
    }
    /**
     * 重新生成支付信息
     * @return [type] [description]
     */
    public function pay(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/pay",$_GET,$_POST,"应用" . $this->client_id . "调用订单重新支付接口");

            $uid      = $this->_post("uid","","缺少用户ID");
            $order_id = $this->_post("oid","","缺少订单ID");
            $pay_type = 0;
            $map = [
                'id'  =>$order_id,
                'uid' =>$uid,
            ];
            $result = apiCall(OrdersApi::GET_INFO,[$map]);
            if(!$result['status']){
                LogRecord($result['info'],__FILE__.__LINE__);
                $this->apiReturnErr($result['info']);
            }
            if(empty($result['info'])) $this->apiReturnErr("订单ID非法!");
            // if(intval($result['createtime']) + 1800 <time()) $this->apiReturnErr('订单已过期');
            $order    = $result['info'];
            $pay_code = $order['order_code'].';';

            $now  = time();
            $total_price = round(floatval($order['price']) - floatval($order['discount_money']) - floatval($order['pay_balance']),2);

            //5. 返回支付编号,用这个支付编号来生成支付信息
            $ordersPayCode = [
                'order_content' =>$pay_code,
                'createtime'    =>$now, //自动完成
                'pay_type'      =>$pay_type,
                'pay_money'     =>$total_price,
                'uid'           =>$uid,
            ];
            $result = apiCall(OrdersPaycodeApi::ADD,[$ordersPayCode]);
            if($result['status']){
                $pay_id = $result['info'];
                $info = $this->getPayReturnInfo($pay_id,$uid,$total_price);
                $this->apiReturnSuc($info);
            }else{
                $this->apiReturnErr("支付信息生成失败!");
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }
    }

    /**
     * 订单取消
     * TODO : ----
     */
    public function cancel(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/qxorder",$_GET,$_POST,"应用" . $this->client_id . "调用订单取消接口");
            $uid        = $this->_post("uid",0,'用户ID缺失');
            $order_code = $this->_post('order_code',0,'订单编号缺失');
            //取消订单+检查+推送
            $r = apiCall(OrderStatusApi::CANCEL,[$order_code,false,$uid]);
            if(!$r['status']) $this->apiReturnErr($r['info']);
            $this->apiReturnSuc($r['info']);
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }

    /**
     * 订单确认收货
     */
    public function sure(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/sureorder",$_GET,$_POST,"应用" . $this->client_id . "调用订单确认收货接口");
            $uid        = $this->_post("uid",0,'用户ID缺失');
            $order_code = $this->_post('order_code',0,'订单编号缺失');
            $result     = apiCall(OrderStatusApi::CONFIRM_RECEIVE,[$order_code,false,$uid]);

            if(!$result['status']) $this->apiReturnErr('确认收货失败!'.$result['info']);
            // 推送消息
            $entity = [
                'from_id' =>0,
                'title'   =>Message::MESSAGE_ORDER,
                'content' =>'编号为'.$order_code.'的订单确认收货成功,等待评价',
                'summary' =>'订单'.$order_code.'已确认收货,期待您的评价',
                'extra'   =>['uid'=>$uid], //消息记录中的
            ];
            $after_open = ['type'=>'go_activity','param'=>Message::MESSAGE_ORDER_ACTIVITY,'extra'=>['order_code'=>$order_code]]; //推送参数
            $r = apiCall(MessageApi::PUSH_MESSAGE_WITH_TYPE,[Message::MESSAGE_ORDER,$entity,$uid,false,$after_open]);
            if(!$r['status']) $this->apiReturnSuc($r['info']);
            $this->apiReturnSuc('成功确认收货!');
        }else{
            $this->apiReturnErr('只支持post请求');
        }
    }

    /**
     * 申请售后
     */
    public function afterSale(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/afterSale",$_GET,$_POST,"应用" . $this->client_id . "调用订单申请售后接口");
            $uid        = $this->_post("uid",0,"缺少用户ID");
            $order_code = $this->_post('order_code','',"无法获取订单!");
            $reason     = $this->_post('reason','无');
            $rtype      = $this->_post('refund_type','','售后类型错误');
            $is_get     = $this->_post('goods_get','','goods_get错误');
            $note       = $this->_post('note','无');
            $money      = $this->_post('refund_money',0);
            $rtype = intval($rtype);
            if(!in_array($rtype,[1,2,3])) $this->apiReturnErr('售后类型错误');
            $is_get = intval($is_get);
            if(!in_array($is_get,[1,2])) $this->apiReturnErr('售后类型错误');
            $map = [
                'order_code'=>$order_code
            ];
            $r = apiCall(OrderRefundApi::GET_INFO,[$map]);
            if(!$r['status']) $this->apiReturnErr('申请售后失败!');
            $refund_info = $r['info'];

            $now = time();
            $entity = ['create_time'=>$now,'reason'=>$reason,'valid_status'=>0,'reply_msg'=>'','reply_time'=>0,'order_code'=>$order_code,'refund_type'=>$rtype,'goods_get'=>$is_get,'note'=>$note,'refund_money'=>$money];
            if(empty($refund_info)){
                // trace(" ==== ");
                // trace($entity);
                $r = apiCall(OrderRefundApi::ADD,[$entity]);
            }else{

                if(0 == $refund_info['valid_status']){
                    //待审核，无法再次申请售后，直接返回提示文字（正在审核中）
                    $this->apiReturnErr('您已经申请过售后，请耐心等待客服处理！');
                }else{
                    //重新发起售后
                    $r = apiCall(OrderRefundApi::SAVE,array($map,$entity));
                }
            }

            if(!$r['status']) $this->apiReturnErr('申请售后失败!信息:'.$r['info']);

            //修改订单的售后状态
            $r = apiCall(OrderRefundApi::CHANGE_SERVICE_STATUS,array($order_code,Orders::CS_PENDING));
            if($r['status']){
                $this->apiReturnSuc('申请售后成功，等待客服反馈!');
            }else{
                $this->apiReturnErr('订单发生未知错误!');
            }

        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }


    /**
     * 获取订单物流信息
     */
    public function express(){
        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/express",$_GET,$_POST,"应用" . $this->client_id . "调用获取订单物流信息接口");
            $order_code = $this->_post("order_code","","订单编号缺失!");
            $uid = $this->_post("uid","","用户编号缺失!");

            $result = apiCall(OrdersExpressApi::GET_INFO,[['order_code'=>$order_code,'uid'=>$uid]]);
            $this->checkApiCallResult($result,false,"发货信息获取失败!");
            $this->apiReturnSuc($result['info']);
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }

    /**
     * 订单分页查询
     */
    public function query(){

        if(IS_POST){
            $this->checkVersion($this->api_ver);
            addLog("Orders/query",$_GET,$_POST,"应用" . $this->client_id . "调用订单分页查询接口");

            $uid      = $this->_post('uid','','用户ID缺失');
            $curpage  = $this->_post('page_no',1);
            $pagesize = $this->_post('page_size',10);
            $status   = $this->_post('status',0);
            $status   = intval($status);
            $curpage  = intval($curpage);
            $pagesize = intval($pagesize);
            if($curpage  < 1 ) $curpage  = 1;
            if($pagesize > 30) $pagesize = 30;
            if($pagesize <= 0) $pagesize = 10;

            $map = ['uid'=>$uid];
            if(!empty($status)){
                $map = array_merge($map,$this->getQueryStatus($status));
            }
            $page = [
                'curpage' => $curpage,
                'size'    => $pagesize
            ];

            $order = "updatetime desc";
            $result = apiCall(OrdersApi::QUERY,[$map,$page,$order]);
            // trace($result);
            // trace("--- ---");
            if($result['status']){
                $orderList = $result['info']['list'];
                $count     = $result['info']['count'];
                if(empty($orderList)){
                    $this->apiReturnSuc($result['info']);
                }
            }else{
                addLog('Orders/query',$_GET,$_POST,$result['info'],true);
                $this->apiReturnErr('查询失败');
            }

            // trace("---mapItem---");
            // trace($result);
            //查询orders_item
            $mapItem = $this->getMapFromResult($orderList);
            // trace("---orderList---");
            // trace($orderList); //order_code 为 key
            $result  = apiCall(OrdersItemApi::QUERY_NO_PAGING,[$mapItem]);
            // trace("---orderitem---");
            // trace($result);
            if($result['status']){
                $list   =  array_values($this->combine($orderList,$result['info']));
                // $return = ['list'=>$list];
                // $return['page_no']   = $curpage;
                // $return['page_size'] = $pagesize;
                foreach ($list as &$v) {
                    $v['count'] = 0;
                    foreach ($v['items'] as $vv) {
                        $v['count'] = $v['count'] + $vv['count'];
                    }
                    $v['count'] = ''.$v['count'];
                }
                $this->apiReturnSuc(['count'=>$count,'list'=>$list]);
            }else{
                addLog('Orders/query',$_GET,$_POST,$result['info'],true);
                $this->apiReturnErr('查询失败');
            }

        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }

    /**
     * 将此处查询状态
     * 转换为订单状态或支付状态
     * @param $status
     * @return array
     */
    private function getQueryStatus($status){
        /*status|order_status
        -|-
        0|全部
        1|待付款【order_status=2,待确认(未付款) - 订单生成】
        2|待发货【order_status=2,待确认(已付款);order_status=3,待发货(已付款)】
        3|待收货【order_status=2,待确认(已付款);order_status=3,待发货(已付款);order_status=4,已发货待收货(已付款)】
        4|已收货【order_status=5,已收货(已付款)】
        5|退款/售后【cs_status=2,售后待处理(已付款);cs_status=3,售后已处理(已付款)】
        6|待评价【order_status=5,已收货(已付款待评价)】*/

        $map = [];
        switch($status){
            case 0:
                break;
            case 1:
                $map['pay_status']   = Orders::ORDER_TOBE_PAID;
                $str = Orders::ORDER_TOBE_SHIPPED.','.Orders::ORDER_TOBE_CONFIRMED;
                $map['_string'] = '`order_status` in ('.$str.')';
                break;
            case 2:
                $map['pay_status']   = Orders::ORDER_PAID;
                $str = Orders::ORDER_TOBE_SHIPPED.','.Orders::ORDER_TOBE_CONFIRMED;
                $map['_string'] = '`order_status` in ('.$str.')';
                break;
            case 3:
                $map['pay_status']   = Orders::ORDER_PAID;
                $str = Orders::ORDER_SHIPPED.','.Orders::ORDER_TOBE_SHIPPED.','.Orders::ORDER_TOBE_CONFIRMED;
                $map['_string'] = '`order_status` in ('.$str.')';
                break;
            case 4:
                $map['pay_status']   = Orders::ORDER_PAID;
                $map['order_status'] = Orders::ORDER_RECEIPT_OF_GOODS;
                break;
            case 5:
                $map['pay_status']   = Orders::ORDER_PAID;
                $str = Orders::CS_PENDING.','.Orders::CS_PROCESSED;
                $map['_string'] = '`cs_status` in ('.$str.')';
                break;
            case 6:
                $map['pay_status']     = Orders::ORDER_PAID;
                $map['order_status']   = Orders::ORDER_RECEIPT_OF_GOODS;
                $map['comment_status'] = Orders::ORDER_TOBE_EVALUATE;
                break;
            default:
                break;
        }
        return $map;
    }

    /**
     * Convert
     * @param  $order_list
     * @return mixed
     */
    private function combine($orderList,$itemList){
        foreach($itemList as $vo){
            $order         = &$orderList[$vo['order_code']];
            // $vo['img_url'] = getImageUrl($vo['img']);
            // unset($vo['img']);
            if(!empty($order)){
                array_push($order['items'],$vo);
            }
        }

        return $orderList;
    }

    private function getMapFromResult(&$list){

        $newList = [];
        $mapItem = [];
        foreach($list as $vo){
            array_push($mapItem,'\''.$vo['order_code'].'\'');
            $newList[$vo['order_code']] = $vo;
            $newList[$vo['order_code']]['items'] = [];
        }
        $list = $newList;
        // return ['order_code'=>['in',$mapItem]];
        return ['_string'=>'order_code in ('.implode(',', $mapItem).')'];
    }

    /**
     *
     * @param array  $r           the result
     * @param bool   $cantBeNull
     * @param string $whenNullMsg 当为空时的信息
     */
    protected function checkApiCallResult($r,$cantBeNull=true,$whenNullMsg="获取信息为空!"){
        if(!$r['status']) $this->apiReturnErr($r['info']);
        if($cantBeNull && empty($r['info'])) $this->apiReturnErr($whenNullMsg);
    }

    /**
     * [checkApiReturn description] domain专用
     * @author rainbow
     * @param  [type]  $r       [the result]
     * @param  string  $err     [description]
     * @param  string  $nullerr [description]
     * @param  boolean $model   事务对象
     * @param  string  $fullerr [description]
     * @return [type]           [description]
     */
    private function checkApiReturn($r,$err=false,$nullerr=false,$model=false,$fullerr=false)
    {
        if(false === $r['status']){
            if(false === $err) $err = $r['info'];
            if(false !== $model) $model->rollback();
            $this->apiReturnErr($err);
        }else{
            if(false !== $nullerr && empty($r['info'])){
                if($model) $model->rollback();
                $this->apiReturnErr($nullerr);
            }
            if(false !== $fullerr && !empty($r['info'])){
                if(false !== $model) $model->rollback();
                $this->apiReturnErr($fullerr);
            }
        }
    }
    //对商品信息进行分组
    private function groupByStore($cart){
        $new_cart = array();

        foreach($cart as $vo){
            $store_id = $vo['store_id'];
            if(!isset($new_cart[$store_id])){
                $new_cart[$store_id] = array();
            }
            array_push($new_cart[$store_id],$vo);
        }
        return $new_cart;
    }

    /**
     * 计算单个订单里的金额
     * @param $address array 收货地址，计算运费用
     * @param $items   array  购物的商品信息，购物车项
     * @param $selfCoupon  array 自己的优惠信息
     * @param $otherCoupon array  其它人的优惠信息，自己可以用，填了优惠码,也可空
     * @return array
     */
    private function calPrice($address,$items){
        $entity = [];
        $entity['count']           = 0; //总件数
        $entity['price']           = 0; //应付金额
        $entity['post_price']      = 0; //运费
        $entity['discount_money']  = 0; //折扣金额数
        $entity['brokerage_ratio'] = 0; //返佣比例
        $entity['tax_amount']      = 0; //税款
        $entity['goods_amount']    = 0; //货款＝商品金额＊数量 总和
        $entity['items']           = [];

        foreach($items as $item){
            //检查购物车中商品最新信息
            $result = apiCall(ProductSkuApi::GET_INFO,[['id'=>$item['psku_id']]]);
            if($result['status']){
                if(empty($result['info'])){
                    // addLog('Orders/calPrice',$item,'购物车ID：'.$item['id'].'商品无效','调试',true);
                    $this->apiReturnErr('购物车ID：'.$item['id'].'商品无效');
                }else{
                    $sku = $result['info'];
                    //判断购物车价格是否最新
                    if($item['price']!=$sku['price']){
                        $this->apiReturnErr('购物车ID：'.$item['id'].'商品价格需要更新');
                    }
                    if($sku['quantity']<$item['count']){
                        $this->apiReturnErr('购物车ID：'.$item['id'].'商品库存不足');
                    }
                    //更新商品信息
                }
            }else{
                $this->apiReturnErr('购物车ID：'.$item['id'].'p_skuid查询失败');
            }

            $post_price = 0;
            $taxAmount =0;

            $cnt = intval($item['count']);
            //TODO:1. 该商品折扣价格
            $discount_price = 0;

            //TODO:2. 该商品使用优惠码之后的价格

            //4. 货款
            $goodsAmount = $cnt * $item['price'];

            //5.应付金额
            $price =  $cnt * ($item['price'] - $discount_price) + $post_price;

            if($price < 0 ){
                LogRecord("商品优惠金额不能为负!",__FILE__.__LINE__);
                $this->apiReturnErr("服务器计算商品价格出错!");
            }

            //1. 优惠金额
            $entity['discount_money'] = $entity['discount_money'] + $cnt*$discount_price;//折扣
            $entity['tax_amount'] = $entity['tax_amount'] + $taxAmount; //税款
            $entity['goods_amount'] = $entity['goods_amount'] + $goodsAmount; //货款
            $entity['post_price'] = $post_price; //运费
            $entity['price'] = $entity['price'] + $price;

            array_push($entity['items'],$item);

        }

        addLog("CalDiscountMoney 计算的应付金额，不含运费",$entity,"","[调试]",true);
        return $entity;
    }

    /**
     * 订单红包检测 - 使用 - 取消退回订单退回
     * @author rainbow
     * TODO : 考虑变为一次查询
     */
    private function useRedEnvelope($idcode,$uid,$price){
        //查询红包
        $r = apiCall(RedEnvelopeApi::GET_INFO,[['id'=>$idcode,'uid'=>$uid,'use_status'=>0]]);
        if(!$r['status'])  return ['status'=>false,'info'=>'获取红包信息失败'];
        if(empty($r['info'])) return ['status'=>false,'info'=>'红包错误'];
        $RedEnvelope = $r['info'];
        if(intval($RedEnvelope['use_status']) === 1) return ['status'=>false,'info'=>'红包已被使用'];
        //是否过期
        $endDate = $RedEnvelope['get_time'] + $RedEnvelope['expire_time'];
        if($endDate < time()) return ['status'=>false,'info'=>'红包过期'];
        //查询模版
        $r = apiCall(RedEnvelopeTplApi::GET_INFO,[['id'=>$RedEnvelope['tpl_id']]]);
        if(!$r['status']) ['status'=>false,'info'=>'获取红包模版失败'];
        if(empty($r['info'])) return ['status'=>false,'info'=>'获取红包模版失败'];
        $RedEnvelopeTpl = $r['info'];
        //是否适用
        if($RedEnvelopeTpl['use_condition']<=$price){
            //满足红包使用条件
            //1.使用红包
            $r = apiCall(RedEnvelopeApi::SAVE_BY_ID,[$idcode,['use_status'=>1]]);
            if(!$r['status']) return ['status'=>false,'info'=>'红包使用失败'];
            return  ['status'=>true,'info'=>$RedEnvelope['money']];
        }else{
            return ['status'=>false,'info'=>'红包不适用'];
        }
        // return ['status'=>false,'info'=>'shit:you can\'t be here'];
    }
    /**
     * 检测优惠券 - 使用 - 取消退回订单退回
     * @author rainbow
     * TODO : 考虑变为一次查询
     */
    private function useCoupon($id,$uid,$price){
        //查询优惠券
        $r = apiCall(CouponApi::GET_INFO,[['id'=>$id,'uid'=>$uid,'use_status'=>0]]);
        if(!$r['status'])     return ['status'=>false,'info'=>$r['info']];
        if(empty($r['info'])) return ['status'=>false,'info'=>'优惠券错误'];
        $Coupon = $r['info'];
        if(intval($Coupon['use_status']) === 1) return ['status'=>false,'info'=>'优惠券已被使用'];
        //是否过期
        $endDate = $Coupon['get_time'] + $Coupon['expire_time'];
        if($endDate < time()) return ['status'=>false,'info'=>'优惠券已过期'];
        //查询模版
        $r = apiCall(CouponTplApi::GET_INFO,[['id'=>$Coupon['tpl_id']]]);
        if(!$r['status']) $this->apiReturnErr('获取优惠券模版失败');
        if(empty($r['info'])) return ['status'=>false,'info'=>'优惠券模版错误'];
        $CouponTpl = $r['info'];
        //是否适用
        if($CouponTpl['use_condition']<=$price){
            //满足优惠券使用条件
            //1.使用优惠券 - 付款成功 改变
            $r = apiCall(CouponApi::SAVE_BY_ID,[$id,['use_status'=>1]]);
            if(!$r['status']) return ['status'=>false,'info'=>'优惠券使用失败'];
            return ['status'=>true,'info'=>$Coupon['money']];
        }else{
            return ['status'=>false,'info'=>'优惠券不适用'];
        }
        // return ['status'=>false,'info'=>'shit:you can\'t be here'];
    }

    /**
     * 从购物车中删除
     * @author 老胖子-何必都 <hebiduhebi@126.com>
     * @editor rainbow
     * @param $uid
     * @param $cart_ids
     */
    private function deleteFromShoppingCart($uid,$cart_ids){
        $map = [
            'uid'     =>$uid,
            // 'id'   =>['in',$cart_ids]
            '_string' =>' id in ('.$cart_ids.')',
        ];
        // $str = '';
        // if($cart_ids && is_array($cart_ids)){
        //     foreach ($cart_ids as $v) {
        //         $str .= $str?$v:','.$v;
        //     }
        //     if($str){
        //         $map['_string'] = ' `id` in ('.$str.') ';
        //     }
        // }else{
        //     $map['id'] = $cart_ids;
        // }
        // trace();
        return apiCall(ShoppingCartApi::DELETE,[$map]);
    }

    private function getPayReturnInfoNew($order_code,$uid,$total_price){
        //保留2位
        $total_price = round($total_price,2);
        $info = array(
            'order_code'=>$order_code,
            //@author 老胖子-何必都 <hebiduhebi@126.com>
            //转换成字符串，否则IOS端解析成数字类型时精度会有问题，比如74.10 被解析成74.09999999999999,从而导致APP端验证失败!
            'total_price'=>strval($total_price)
        );
        $encode = urlencode($order_code.$total_price);
        $encode = md5(strtolower($encode));

        $info['key'] = pay_encrypt_md5($encode);
        return $info;
    }
    private function getPayReturnInfo($pay_id,$uid,$total_price){
        $now = time();

        $code = 'T'.$now.'U'.$uid.'P'.$pay_id;
        $name = '订单'.$code;
        $desc = $name;
        //保留2位
        $total_price = round($total_price,2);
        $info = array(
            'code'=>$code,
            'name'=>$name,
            'desc'=>$desc,
            //@author 老胖子-何必都 <hebiduhebi@126.com>
            //转换成字符串，否则IOS端解析成数字类型时精度会有问题，比如74.10 被解析成74.09999999999999,从而导致APP端验证失败!
            'total_price'=>strval($total_price)
        );

        $encode = urlencode($code.$name.$desc.$total_price);
        $encode = md5(strtolower($encode));

        $info['key'] = pay_encrypt_md5($encode);
        $info['show_url'] = C('SITE_URL')?C('SITE_URL'):'';//支付成功跳转地址 - 订单

        return $info;
    }

    /**
     * Convert
     * @param $order_list
     * @return mixed
     */
    private function convertDetail($list){
        foreach($list as &$vo) {
            $vo['img_url'] = getImageUrl($vo['img']);
        }
        return $list;
    }

    /**
     * 获取运费金额
     */
    private function getPostPrice($info = [],$address_id,$uid){
        $r = apiCall('index/FreightDomain/calc',[$info,$address_id,$uid],'domain');
    // private function getPostPrice($cart_id,$address_id,$uid){
        // $r = apiCall('index/FreightDomain/calc',[$cart_id,$address_id,$uid],'domain');
        if(!$r['status']) return ['status'=>false,'info'=>$r['info']];
        return ['status'=>true,'info'=>$r['info']];
        // $this->apiReturnErr('you can\'t be here');
    }
    /**
     * 关键词过滤
     */
    private function commentFilter($posts){
        $r = apiCall(FilterKeyWordsApi::FILTER,[$posts]);
        return $r['info'];
    }

    private function filter($c=''){
        if(empty($c)) return '';
        if(is_array($c)){
            foreach ($c as &$v) {
                $v = $this->filter($v);
            }
        }else{
        }
        return;
    }
    private function groupWithPid($cart_ids = array()){
        // $map = array(
        //     'id' => array('in',$cart_ids)
        // );
        $map = '`id` in ('.implode($cart_ids,',').')';
        $result = apiCall(ShoppingCartApi::QUERY_NO_PAGING,array($map));
        if(!$result['status']){
            return array('status'=>false,'info'=>$result['info']);
        }
        $data = array();
        foreach($result['info'] as $val){
            if(!isset($data[$val['p_id']])) $data[$val['p_id']] = array();
            array_push($data[$val['p_id']],$val);
        }
        return array('status'=>true,'info'=>$data);
    }
}